/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.configuration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import junit.framework.TestCase;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.configuration.HierarchicalConfiguration.Node;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.configuration.tree.DefaultConfigurationNode;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.ExpressionEngine;
/**
* Test class for HierarchicalConfiguration.
*
* @version $Id: TestHierarchicalConfiguration.java 722238 2008-12-01 21:28:31Z oheger $
*/
public class TestHierarchicalConfiguration extends TestCase
{
private static String[] tables = { "users", "documents" };
private static String[][] fields =
{
{ "uid", "uname", "firstName", "lastName", "email" },
{ "docid", "name", "creationDate", "authorID", "version" }
};
private HierarchicalConfiguration config;
protected void setUp() throws Exception
{
/**
* Initialize the configuration with the following structure:
*
* tables
* table
* name
* fields
* field
* name
* field
* name
*/
config = new HierarchicalConfiguration();
HierarchicalConfiguration.Node nodeTables = createNode("tables", null);
for(int i = 0; i < tables.length; i++)
{
HierarchicalConfiguration.Node nodeTable = createNode("table", null);
nodeTables.addChild(nodeTable);
HierarchicalConfiguration.Node nodeName = createNode("name", tables[i]);
nodeTable.addChild(nodeName);
HierarchicalConfiguration.Node nodeFields = createNode("fields", null);
nodeTable.addChild(nodeFields);
for (int j = 0; j < fields[i].length; j++)
{
nodeFields.addChild(createFieldNode(fields[i][j]));
}
}
config.getRoot().addChild(nodeTables);
}
public void testSetRoot()
{
try
{
config.setRoot(null);
fail("Could set null root node!");
}
catch(IllegalArgumentException iex)
{
//ok
}
config.setRoot(new HierarchicalConfiguration.Node("test"));
assertTrue(config.isEmpty());
}
public void testSetRootNode()
{
config.setRootNode(new DefaultConfigurationNode("testNode"));
assertNotSame("Same root node", config.getRootNode(), config.getRoot());
assertEquals("Wrong name of root node", "testNode", config.getRoot().getName());
config.setRootNode(new HierarchicalConfiguration.Node("test"));
assertSame("Wrong root node", config.getRootNode(), config.getRoot());
}
public void testSetRootNodeNull()
{
try
{
config.setRootNode(null);
fail("Could set null root node!");
}
catch(IllegalArgumentException iex)
{
//ok
}
}
public void testIsEmpty()
{
assertFalse(config.isEmpty());
HierarchicalConfiguration conf2 = new HierarchicalConfiguration();
assertTrue(conf2.isEmpty());
HierarchicalConfiguration.Node child1 = new HierarchicalConfiguration.Node("child1");
HierarchicalConfiguration.Node child2 = new HierarchicalConfiguration.Node("child2");
child1.addChild(child2);
conf2.getRoot().addChild(child1);
assertTrue(conf2.isEmpty());
}
public void testGetProperty()
{
assertNull(config.getProperty("tables.table.resultset"));
assertNull(config.getProperty("tables.table.fields.field"));
Object prop = config.getProperty("tables.table(0).fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(5, ((Collection) prop).size());
prop = config.getProperty("tables.table.fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(10, ((Collection) prop).size());
prop = config.getProperty("tables.table.fields.field(3).name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(2, ((Collection) prop).size());
prop = config.getProperty("tables.table(1).fields.field(2).name");
assertNotNull(prop);
assertEquals("creationDate", prop.toString());
}
public void testSetProperty()
{
config.setProperty("tables.table(0).name", "resources");
assertEquals("resources", config.getString("tables.table(0).name"));
config.setProperty("tables.table.name", "tab1,tab2");
assertEquals("tab1", config.getString("tables.table(0).name"));
assertEquals("tab2", config.getString("tables.table(1).name"));
config.setProperty("test.items.item", new int[] { 2, 4, 8, 16 });
assertEquals(3, config.getMaxIndex("test.items.item"));
assertEquals(8, config.getInt("test.items.item(2)"));
config.setProperty("test.items.item(2)", new Integer(6));
assertEquals(6, config.getInt("test.items.item(2)"));
config.setProperty("test.items.item(2)", new int[] { 7, 9, 11 });
assertEquals(5, config.getMaxIndex("test.items.item"));
config.setProperty("test", Boolean.TRUE);
config.setProperty("test.items", "01/01/05");
assertEquals(5, config.getMaxIndex("test.items.item"));
assertTrue(config.getBoolean("test"));
assertEquals("01/01/05", config.getProperty("test.items"));
config.setProperty("test.items.item", new Integer(42));
assertEquals(0, config.getMaxIndex("test.items.item"));
assertEquals(42, config.getInt("test.items.item"));
}
public void testClearProperty()
{
config.clearProperty("tables.table(0).fields.field(0).name");
assertEquals("uname", config.getProperty("tables.table(0).fields.field(0).name"));
config.clearProperty("tables.table(0).name");
assertFalse(config.containsKey("tables.table(0).name"));
assertEquals("firstName", config.getProperty("tables.table(0).fields.field(1).name"));
assertEquals("documents", config.getProperty("tables.table.name"));
config.clearProperty("tables.table");
assertEquals("documents", config.getProperty("tables.table.name"));
config.addProperty("test", "first");
config.addProperty("test.level", "second");
config.clearProperty("test");
assertEquals("second", config.getString("test.level"));
assertFalse(config.containsKey("test"));
}
public void testClearTree()
{
Object prop = config.getProperty("tables.table(0).fields.field.name");
assertNotNull(prop);
config.clearTree("tables.table(0).fields.field(3)");
prop = config.getProperty("tables.table(0).fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(4, ((Collection) prop).size());
config.clearTree("tables.table(0).fields");
assertNull(config.getProperty("tables.table(0).fields.field.name"));
prop = config.getProperty("tables.table.fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(5, ((Collection) prop).size());
config.clearTree("tables.table(1)");
assertNull(config.getProperty("tables.table.fields.field.name"));
}
/**
* Tests removing more complex node structures.
*/
public void testClearTreeComplex()
{
final int count = 5;
// create the structure
for (int idx = 0; idx < count; idx++)
{
config.addProperty("indexList.index(-1)[@default]", Boolean.FALSE);
config.addProperty("indexList.index[@name]", "test" + idx);
config.addProperty("indexList.index.dir", "testDir" + idx);
}
assertEquals("Wrong number of nodes", count - 1, config
.getMaxIndex("indexList.index[@name]"));
// Remove a sub tree
boolean found = false;
for (int idx = 0; true; idx++)
{
String name = config.getString("indexList.index(" + idx
+ ")[@name]");
if (name == null)
{
break;
}
if ("test3".equals(name))
{
assertEquals("Wrong dir", "testDir3", config
.getString("indexList.index(" + idx + ").dir"));
config.clearTree("indexList.index(" + idx + ")");
found = true;
}
}
assertTrue("Key to remove not found", found);
assertEquals("Wrong number of nodes after remove", count - 2, config
.getMaxIndex("indexList.index[@name]"));
assertEquals("Wrong number of dir nodes after remove", count - 2,
config.getMaxIndex("indexList.index.dir"));
// Verify
for (int idx = 0; true; idx++)
{
String name = config.getString("indexList.index(" + idx
+ ")[@name]");
if (name == null)
{
break;
}
if ("test3".equals(name))
{
fail("Key was not removed!");
}
}
}
/**
* Tests the clearTree() method on a hierarchical structure of nodes. This
* is a test case for CONFIGURATION-293.
*/
public void testClearTreeHierarchy()
{
config.addProperty("a.b.c", "c");
config.addProperty("a.b.c.d", "d");
config.addProperty("a.b.c.d.e", "e");
config.clearTree("a.b.c");
assertFalse("Property not removed", config.containsKey("a.b.c"));
assertFalse("Sub property not removed", config.containsKey("a.b.c.d"));
}
public void testContainsKey()
{
assertTrue(config.containsKey("tables.table(0).name"));
assertTrue(config.containsKey("tables.table(1).name"));
assertFalse(config.containsKey("tables.table(2).name"));
assertTrue(config.containsKey("tables.table(0).fields.field.name"));
assertFalse(config.containsKey("tables.table(0).fields.field"));
config.clearTree("tables.table(0).fields");
assertFalse(config.containsKey("tables.table(0).fields.field.name"));
assertTrue(config.containsKey("tables.table.fields.field.name"));
}
public void testGetKeys()
{
List keys = new ArrayList();
for (Iterator it = config.getKeys(); it.hasNext();)
{
keys.add(it.next());
}
assertEquals(2, keys.size());
assertTrue(keys.contains("tables.table.name"));
assertTrue(keys.contains("tables.table.fields.field.name"));
// test the order of the keys returned
config.addProperty("order.key1", "value1");
config.addProperty("order.key2", "value2");
config.addProperty("order.key3", "value3");
Iterator it = config.getKeys("order");
assertEquals("1st key", "order.key1", it.next());
assertEquals("2nd key", "order.key2", it.next());
assertEquals("3rd key", "order.key3", it.next());
}
public void testGetKeysString()
{
// add some more properties to make it more interesting
config.addProperty("tables.table(0).fields.field(1).type", "VARCHAR");
config.addProperty("tables.table(0)[@type]", "system");
config.addProperty("tables.table(0).size", "42");
config.addProperty("tables.table(0).fields.field(0).size", "128");
config.addProperty("connections.connection.param.url", "url1");
config.addProperty("connections.connection.param.user", "me");
config.addProperty("connections.connection.param.pwd", "secret");
config.addProperty("connections.connection(-1).param.url", "url2");
config.addProperty("connections.connection(1).param.user", "guest");
checkKeys("tables.table(1)", new String[] { "name", "fields.field.name" });
checkKeys("tables.table(0)",
new String[] { "name", "fields.field.name", "tables.table(0)[@type]", "size", "fields.field.type", "fields.field.size" });
checkKeys("connections.connection(0).param",
new String[] {"url", "user", "pwd" });
checkKeys("connections.connection(1).param",
new String[] {"url", "user" });
}
/**
* Tests getKeys() with a prefix when the prefix matches exactly a key.
*/
public void testGetKeysWithKeyAsPrefix()
{
config.addProperty("order.key1", "value1");
config.addProperty("order.key2", "value2");
Iterator it = config.getKeys("order.key1");
assertTrue("no key found", it.hasNext());
assertEquals("1st key", "order.key1", it.next());
assertFalse("more keys than expected", it.hasNext());
}
/**
* Tests getKeys() with a prefix when the prefix matches exactly a key, and
* there are multiple keys starting with this prefix.
*/
public void testGetKeysWithKeyAsPrefixMultiple()
{
config.addProperty("order.key1", "value1");
config.addProperty("order.key1.test", "value2");
config.addProperty("order.key1.test.complex", "value2");
Iterator it = config.getKeys("order.key1");
assertEquals("Wrong key 1", "order.key1", it.next());
assertEquals("Wrong key 2", "order.key1.test", it.next());
assertEquals("Wrong key 3", "order.key1.test.complex", it.next());
assertFalse("More keys than expected", it.hasNext());
}
public void testAddProperty()
{
config.addProperty("tables.table(0).fields.field(-1).name", "phone");
Object prop = config.getProperty("tables.table(0).fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(6, ((Collection) prop).size());
config.addProperty("tables.table(0).fields.field.name", "fax");
prop = config.getProperty("tables.table.fields.field(5).name");
assertNotNull(prop);
assertTrue(prop instanceof List);
List list = (List) prop;
assertEquals("phone", list.get(0));
assertEquals("fax", list.get(1));
config.addProperty("tables.table(-1).name", "config");
prop = config.getProperty("tables.table.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(3, ((Collection) prop).size());
config.addProperty("tables.table(2).fields.field(0).name", "cid");
config.addProperty("tables.table(2).fields.field(-1).name",
"confName");
prop = config.getProperty("tables.table(2).fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(2, ((Collection) prop).size());
assertEquals("confName",
config.getProperty("tables.table(2).fields.field(1).name"));
config.addProperty("connection.user", "scott");
config.addProperty("connection.passwd", "tiger");
assertEquals("tiger", config.getProperty("connection.passwd"));
ConfigurationKey key = new ConfigurationKey();
key.append("tables").append("table").appendIndex(0);
key.appendAttribute("tableType");
config.addProperty(key.toString(), "system");
assertEquals("system", config.getProperty(key.toString()));
try
{
config.addProperty(".", "InvalidKey");
fail("Could add invalid key!");
}
catch(IllegalArgumentException iex)
{
//ok
}
}
public void testGetMaxIndex()
{
assertEquals(4, config.getMaxIndex("tables.table(0).fields.field"));
assertEquals(4, config.getMaxIndex("tables.table(1).fields.field"));
assertEquals(1, config.getMaxIndex("tables.table"));
assertEquals(1, config.getMaxIndex("tables.table.name"));
assertEquals(0, config.getMaxIndex("tables.table(0).name"));
assertEquals(0, config.getMaxIndex("tables.table(1).fields.field(1)"));
assertEquals(-1, config.getMaxIndex("tables.table(2).fields"));
int maxIdx = config.getMaxIndex("tables.table(0).fields.field.name");
for(int i = 0; i <= maxIdx; i++)
{
ConfigurationKey key = new ConfigurationKey("tables.table(0).fields");
key.append("field").appendIndex(i).append("name");
assertNotNull(config.getProperty(key.toString()));
}
}
public void testSubset()
{
// test the subset on the first table
Configuration subset = config.subset("tables.table(0)");
assertEquals(tables[0], subset.getProperty("name"));
Object prop = subset.getProperty("fields.field.name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(5, ((Collection) prop).size());
for (int i = 0; i < fields[0].length; i++)
{
ConfigurationKey key = new ConfigurationKey();
key.append("fields").append("field").appendIndex(i);
key.append("name");
assertEquals(fields[0][i], subset.getProperty(key.toString()));
}
// test the subset on the second table
assertTrue("subset is not empty", config.subset("tables.table(2)").isEmpty());
// test the subset on the fields
subset = config.subset("tables.table.fields.field");
prop = subset.getProperty("name");
assertTrue("prop is not a collection", prop instanceof Collection);
assertEquals(10, ((Collection) prop).size());
assertEquals(fields[0][0], subset.getProperty("name(0)"));
// test the subset on the field names
subset = config.subset("tables.table.fields.field.name");
assertTrue("subset is not empty", subset.isEmpty());
}
/**
* Tests the subset() method when the specified node has a value. This value
* must be available in the subset, too. Related to CONFIGURATION-295.
*/
public void testSubsetNodeWithValue()
{
config.setProperty("tables.table(0).fields", "My fields");
Configuration subset = config.subset("tables.table(0).fields");
assertEquals("Wrong field name", fields[0][0], subset
.getString("field(0).name"));
assertEquals("Wrong value of root", "My fields", subset.getString(""));
}
/**
* Tests the subset() method when the specified key selects multiple keys.
* The resulting root node should have a value only if exactly one of the
* selected nodes has a value. Related to CONFIGURATION-295.
*/
public void testSubsetMultipleNodesWithValues()
{
config.setProperty("tables.table(0).fields", "My fields");
Configuration subset = config.subset("tables.table.fields");
assertEquals("Wrong value of root", "My fields", subset.getString(""));
config.setProperty("tables.table(1).fields", "My other fields");
subset = config.subset("tables.table.fields");
assertNull("Root value is not null though there are multiple values",
subset.getString(""));
}
/**
* Tests the configurationAt() method to obtain a configuration for a sub
* tree.
*/
public void testConfigurationAt()
{
HierarchicalConfiguration subConfig = config
.configurationAt("tables.table(1)");
assertEquals("Wrong table name", tables[1], subConfig.getString("name"));
List lstFlds = subConfig.getList("fields.field.name");
assertEquals("Wrong number of fields", fields[1].length, lstFlds.size());
for (int i = 0; i < fields[1].length; i++)
{
assertEquals("Wrong field at position " + i, fields[1][i], lstFlds
.get(i));
}
subConfig.setProperty("name", "testTable");
assertEquals("Change not visible in parent", "testTable", config
.getString("tables.table(1).name"));
config.setProperty("tables.table(1).fields.field(2).name", "testField");
assertEquals("Change not visible in sub config", "testField", subConfig
.getString("fields.field(2).name"));
}
/**
* Tests the configurationAt() method when the passed in key does not exist.
*/
public void testConfigurationAtUnknownSubTree()
{
try
{
config.configurationAt("non.existing.key");
fail("Could obtain sub config for unknown key!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests the configurationAt() method when the passed in key selects
* multiple nodes. This should cause an exception.
*/
public void testConfigurationAtMultipleNodes()
{
try
{
config.configurationAt("tables.table.name");
fail("Could create sub config with non unique key!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests the configurationsAt() method.
*/
public void testConfigurationsAt()
{
List lstFlds = config.configurationsAt("tables.table(1).fields.field");
assertEquals("Wrong size of fields", fields[1].length, lstFlds.size());
for (int i = 0; i < fields[1].length; i++)
{
HierarchicalConfiguration sub = (HierarchicalConfiguration) lstFlds
.get(i);
assertEquals("Wrong field at position " + i, fields[1][i], sub
.getString("name"));
}
}
/**
* Tests the configurationsAt() method when the passed in key does not
* select any sub nodes.
*/
public void testConfigurationsAtEmpty()
{
assertTrue("List is not empty", config.configurationsAt("unknown.key")
.isEmpty());
}
public void testClone()
{
Configuration copy = (Configuration) config.clone();
assertTrue(copy instanceof HierarchicalConfiguration);
checkContent(copy);
}
/**
* Tests whether registered event handlers are handled correctly when a
* configuration is cloned. They should not be registered at the clone.
*/
public void testCloneWithEventListeners()
{
config.addConfigurationListener(new ConfigurationListener()
{
public void configurationChanged(ConfigurationEvent event)
{
// just a dummy
}
});
HierarchicalConfiguration copy = (HierarchicalConfiguration) config
.clone();
assertTrue("Event listener registered at clone", copy
.getConfigurationListeners().isEmpty());
}
public void testAddNodes()
{
Collection nodes = new ArrayList();
nodes.add(createFieldNode("birthDate"));
nodes.add(createFieldNode("lastLogin"));
nodes.add(createFieldNode("language"));
config.addNodes("tables.table(0).fields", nodes);
assertEquals(7, config.getMaxIndex("tables.table(0).fields.field"));
assertEquals("birthDate", config.getString("tables.table(0).fields.field(5).name"));
assertEquals("lastLogin", config.getString("tables.table(0).fields.field(6).name"));
assertEquals("language", config.getString("tables.table(0).fields.field(7).name"));
}
/**
* Tests the addNodes() method when the provided key does not exist. In
* this case, a new node (or even a complete new branch) will be created.
*/
public void testAddNodesForNonExistingKey()
{
Collection nodes = new ArrayList();
nodes.add(createNode("usr", "scott"));
Node nd = createNode("pwd", "tiger");
nd.setAttribute(true);
nodes.add(nd);
config.addNodes("database.connection.settings", nodes);
assertEquals("Usr node not found", "scott", config.getString("database.connection.settings.usr"));
assertEquals("Pwd node not found", "tiger", config.getString("database.connection.settings[@pwd]"));
}
/**
* Tests the addNodes() method when the new nodes should be added to an
* attribute node. This is not allowed.
*/
public void testAddNodesWithAttributeKey()
{
Collection nodes = new ArrayList();
nodes.add(createNode("testNode", "yes"));
try
{
config.addNodes("database.connection[@settings]", nodes);
fail("Could add nodes to an attribute node!");
}
catch(IllegalArgumentException iex)
{
//ok
}
}
/**
* Tests copying nodes from one configuration to another one.
*/
public void testAddNodesCopy()
{
HierarchicalConfiguration configDest = new HierarchicalConfiguration();
configDest.addProperty("test", "TEST");
Collection nodes = config.getRootNode().getChildren();
assertEquals("Wrong number of children", 1, nodes.size());
configDest.addNodes("newNodes", nodes);
for (int i = 0; i < tables.length; i++)
{
String keyTab = "newNodes.tables.table(" + i + ").";
assertEquals("Table " + i + " not found", tables[i], configDest
.getString(keyTab + "name"));
for (int j = 0; j < fields[i].length; j++)
{
assertEquals("Invalid field " + j + " in table " + i,
fields[i][j], configDest.getString(keyTab
+ "fields.field(" + j + ").name"));
}
}
}
/**
* Tests adding an attribute node with the addNodes() method.
*/
public void testAddNodesAttributeNode()
{
Collection nodes = new ArrayList();
ConfigurationNode nd = createNode("length", "10");
nd.setAttribute(true);
nodes.add(nd);
config.addNodes("tables.table(0).fields.field(1)", nodes);
assertEquals("Attribute was not added", "10", config
.getString("tables.table(0).fields.field(1)[@length]"));
}
/**
* Tests removing children from a configuration node.
*/
public void testNodeRemove()
{
HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(
"parent", "test");
assertFalse(node.hasChildren());
node.removeChildren(); // should have no effect
assertFalse(node.remove("child"));
node.addChild(createNode("test", "test"));
assertTrue(node.hasChildren());
assertTrue(node.remove("test"));
assertFalse(node.hasChildren());
for (int i = 0; i < 10; i++)
{
node.addChild(createNode("child" + i, "test" + i));
}
assertTrue(node.hasChildren());
assertFalse(node.remove("child"));
assertTrue(node.remove("child2"));
assertTrue(node.getChildren("child2").isEmpty());
HierarchicalConfiguration.Node child = createNode("child0", "testChild");
assertFalse(node.remove(child));
node.addChild(child);
assertTrue(node.remove(child));
assertEquals(1, node.getChildren("child0").size());
assertEquals("test0", ((HierarchicalConfiguration.Node) node
.getChildren("child0").get(0)).getValue());
assertTrue(node.remove("child0"));
assertFalse(node.remove(child));
node.removeChildren();
assertTrue(node.getChildren().isEmpty());
assertFalse(node.remove(child));
}
/**
* Tests the visitor mechanism.
*/
public void testNodeVisitor()
{
CountVisitor v = new CountVisitor();
config.getRoot().visit(v, null);
assertEquals(28, v.beforeCount);
assertEquals(v.beforeCount, v.afterCount);
}
/**
* Tests setting a custom expression engine, which uses a slightly different
* syntax.
*/
public void testSetExpressionEngine()
{
config.setExpressionEngine(null);
assertNotNull("Expression engine is null", config.getExpressionEngine());
assertSame("Default engine is not used", HierarchicalConfiguration
.getDefaultExpressionEngine(), config.getExpressionEngine());
config.setExpressionEngine(createAlternativeExpressionEngine());
checkAlternativeSyntax();
}
/**
* Tests setting the default expression engine. This should impact all
* configuration instances that do not have their own engine.
*/
public void testSetDefaultExpressionEngine()
{
ExpressionEngine engineOld = HierarchicalConfiguration.getDefaultExpressionEngine();
HierarchicalConfiguration
.setDefaultExpressionEngine(createAlternativeExpressionEngine());
checkAlternativeSyntax();
HierarchicalConfiguration.setDefaultExpressionEngine(engineOld);
}
/**
* Tests setting the default expression engine to null. This should not be
* allowed.
*/
public void testSetDefaultExpressionEngineNull()
{
try
{
HierarchicalConfiguration.setDefaultExpressionEngine(null);
fail("Could set default expression engine to null!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests the copy constructor.
*/
public void testInitCopy()
{
HierarchicalConfiguration copy = new HierarchicalConfiguration(config);
checkContent(copy);
}
/**
* Tests whether the nodes of a copied configuration are independent from
* the source configuration.
*/
public void testInitCopyUpdate()
{
HierarchicalConfiguration copy = new HierarchicalConfiguration(config);
config.setProperty("tables.table(0).name", "NewTable");
checkContent(copy);
}
/**
* Tests interpolation facilities.
*/
public void testInterpolation()
{
config.addProperty("base.dir", "/home/foo");
config.addProperty("test.absolute.dir.dir1", "${base.dir}/path1");
config.addProperty("test.absolute.dir.dir2", "${base.dir}/path2");
config.addProperty("test.absolute.dir.dir3", "${base.dir}/path3");
Configuration sub = config.subset("test.absolute.dir");
for (int i = 1; i < 4; i++)
{
assertEquals("Wrong interpolation in parent", "/home/foo/path" + i,
config.getString("test.absolute.dir.dir" + i));
assertEquals("Wrong interpolation in subnode",
"/home/foo/path" + i, sub.getString("dir" + i));
}
}
/**
* Basic interpolation tests.
*/
public void testInterpolationBasic()
{
InterpolationTestHelper.testInterpolation(config);
}
/**
* Tests multiple levels of interpolation.
*/
public void testInterpolationMultipleLevels()
{
InterpolationTestHelper.testMultipleInterpolation(config);
}
/**
* Tests an invalid interpolation that causes an endless loop.
*/
public void testInterpolationLoop()
{
InterpolationTestHelper.testInterpolationLoop(config);
}
/**
* Tests interpolation with a subset.
*/
public void testInterpolationSubset()
{
InterpolationTestHelper.testInterpolationSubset(config);
}
/**
* Tests interpolation of a variable, which cannot be resolved.
*/
public void testInterpolationUnknownProperty()
{
InterpolationTestHelper.testInterpolationUnknownProperty(config);
}
/**
* Tests interpolation with system properties.
*/
public void testInterpolationSysProperties()
{
InterpolationTestHelper.testInterpolationSystemProperties(config);
}
/**
* Tests interpolation with constant values.
*/
public void testInterpolationConstants()
{
InterpolationTestHelper.testInterpolationConstants(config);
}
/**
* Tests escaping variables.
*/
public void testInterpolationEscaped()
{
InterpolationTestHelper.testInterpolationEscaped(config);
}
/**
* Tests manipulating the interpolator.
*/
public void testInterpolator()
{
InterpolationTestHelper.testGetInterpolator(config);
}
/**
* Tests obtaining a configuration with all variables substituted.
*/
public void testInterpolatedConfiguration()
{
HierarchicalConfiguration c = (HierarchicalConfiguration) InterpolationTestHelper
.testInterpolatedConfiguration(config);
// tests whether the hierarchical structure has been maintained
config = c;
testGetProperty();
}
/**
* Tests the copy constructor when a null reference is passed.
*/
public void testInitCopyNull()
{
HierarchicalConfiguration copy = new HierarchicalConfiguration(null);
assertTrue("Configuration not empty", copy.isEmpty());
}
/**
* Tests the parents of nodes when setRootNode() is involved. This is
* related to CONFIGURATION-334.
*/
public void testNodeParentsAfterSetRootNode()
{
DefaultConfigurationNode root = new DefaultConfigurationNode();
DefaultConfigurationNode child1 = new DefaultConfigurationNode(
"child1", "test1");
root.addChild(child1);
config.setRootNode(root);
config.addProperty("child2", "test2");
List nodes = config.getExpressionEngine().query(config.getRootNode(),
"child2");
assertEquals("Wrong number of result nodes", 1, nodes.size());
ConfigurationNode child2 = (ConfigurationNode) nodes.get(0);
assertEquals("Different parent nodes", child1.getParentNode(), child2
.getParentNode());
}
/**
* Tests calling getRoot() after a root node was set using setRootNode() and
* further child nodes have been added. The newly add child nodes should be
* present in the root node returned.
*/
public void testGetRootAfterSetRootNode()
{
DefaultConfigurationNode root = new DefaultConfigurationNode();
DefaultConfigurationNode child1 = new DefaultConfigurationNode(
"child1", "test1");
root.addChild(child1);
config.setRootNode(root);
config.addProperty("child2", "test2");
ConfigurationNode oldRoot = config.getRoot();
assertEquals("Wrong number of children", 2, oldRoot.getChildrenCount());
}
/**
* Helper method for testing the getKeys(String) method.
*
* @param prefix the key to pass into getKeys()
* @param expected the expected result
*/
private void checkKeys(String prefix, String[] expected)
{
Set values = new HashSet();
for(int i = 0; i < expected.length; i++)
{
values.add((expected[i].startsWith(prefix)) ? expected[i] : prefix + "." + expected[i]);
}
Iterator itKeys = config.getKeys(prefix);
while(itKeys.hasNext())
{
String key = (String) itKeys.next();
if(!values.contains(key))
{
fail("Found unexpected key: " + key);
}
else
{
values.remove(key);
}
}
assertTrue("Remaining keys " + values, values.isEmpty());
}
/**
* Helper method for checking keys using an alternative syntax.
*/
private void checkAlternativeSyntax()
{
assertNull(config.getProperty("tables/table/resultset"));
assertNull(config.getProperty("tables/table/fields/field"));
Object prop = config.getProperty("tables/table[0]/fields/field/name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(5, ((Collection) prop).size());
prop = config.getProperty("tables/table/fields/field/name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(10, ((Collection) prop).size());
prop = config.getProperty("tables/table/fields/field[3]/name");
assertNotNull(prop);
assertTrue(prop instanceof Collection);
assertEquals(2, ((Collection) prop).size());
prop = config.getProperty("tables/table[1]/fields/field[2]/name");
assertNotNull(prop);
assertEquals("creationDate", prop.toString());
Set keys = new HashSet();
CollectionUtils.addAll(keys, config.getKeys());
assertEquals("Wrong number of defined keys", 2, keys.size());
assertTrue("Key not found", keys.contains("tables/table/name"));
assertTrue("Key not found", keys
.contains("tables/table/fields/field/name"));
}
/**
* Checks the content of the passed in configuration object. Used by some
* tests that copy a configuration.
*
* @param c the configuration to check
*/
private void checkContent(Configuration c)
{
for (int i = 0; i < tables.length; i++)
{
assertEquals(tables[i], c.getString("tables.table(" + i + ").name"));
for (int j = 0; j < fields[i].length; j++)
{
assertEquals(fields[i][j], c.getString("tables.table(" + i
+ ").fields.field(" + j + ").name"));
}
}
}
private ExpressionEngine createAlternativeExpressionEngine()
{
DefaultExpressionEngine engine = new DefaultExpressionEngine();
engine.setPropertyDelimiter("/");
engine.setIndexStart("[");
engine.setIndexEnd("]");
return engine;
}
/**
* Helper method for creating a field node with its children.
*
* @param name the name of the field
* @return the field node
*/
private static HierarchicalConfiguration.Node createFieldNode(String name)
{
HierarchicalConfiguration.Node fld = createNode("field", null);
fld.addChild(createNode("name", name));
return fld;
}
/**
* Helper method for creating a configuration node.
* @param name the node's name
* @param value the node's value
* @return the new node
*/
private static HierarchicalConfiguration.Node createNode(String name, Object value)
{
HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node(name);
node.setValue(value);
return node;
}
/**
* A test visitor implementation for checking whether all visitor methods
* are correctly called.
*/
static class CountVisitor extends HierarchicalConfiguration.NodeVisitor
{
public int beforeCount;
public int afterCount;
public void visitAfterChildren(Node node, ConfigurationKey key)
{
super.visitAfterChildren(node, key);
afterCount++;
}
public void visitBeforeChildren(Node node, ConfigurationKey key)
{
super.visitBeforeChildren(node, key);
beforeCount++;
}
}
}